//
//  PhoneNumber.m
//  Phone
//
//  Created by ideveloper on 2024/6/25.
//

#import "PhoneNumber.h"

@implementation PhoneNumber

- (instancetype)initWithDatFile:(NSString *)datFile {
    self = [super init];
    if (self) {
        if (!datFile) {
            datFile = [[NSBundle mainBundle] pathForResource:@"phone" ofType:@"dat"];
        }
        self.datFile = datFile;
        self.buf = [NSData dataWithContentsOfFile:self.datFile];

        self.headFmtLength = 8;
        self.phoneFmtLength = 9;

        [self.buf getBytes:&_version range:NSMakeRange(0, 4)];
        [self.buf getBytes:&_firstPhoneRecordOffset range:NSMakeRange(4, 4)];

        self.phoneRecordCount = (int)(self.buf.length - self.firstPhoneRecordOffset) / self.phoneFmtLength;
    }
    return self;
}

- (void)getPhoneDatMsg {
    NSLog(@"版本号:%d", self.version);
    NSLog(@"总记录条数:%d", self.phoneRecordCount);
    NSLog(@"dat_file:%@", self.datFile);
}

+ (NSString *)getPhoneNoType:(int)no {
    switch (no) {
        case 4:
            return @"电信虚拟运营商";
        case 5:
            return @"联通虚拟运营商";
        case 6:
            return @"移动虚拟运营商";
        case 3:
            return @"电信";
        case 2:
            return @"联通";
        case 1:
            return @"移动";
        case 7:
            return @"广电";
        case 8:
            return @"广电虚拟运营商";
        default:
            return @"未知";
    }
}

+ (NSDictionary *)_formatPhoneContentWithPhoneNum:(NSString *)phoneNum recordContent:(NSString *)recordContent phoneType:(int)phoneType {
    NSArray *components = [recordContent componentsSeparatedByString:@"|"];
    if (components.count < 4) {
        return nil;
    }
    return @{
        @"phone": phoneNum,
        @"province": components[0],
        @"city": components[1],
        @"zip_code": components[2],
        @"area_code": components[3],
        @"phone_type": [PhoneNumber getPhoneNoType:phoneType]
    };
}

- (NSDictionary *)_lookupPhone:(NSString *)phoneNum {
    if (phoneNum.length < 7 || phoneNum.length > 11) {
        return nil;
    }

    int intPhone = [[phoneNum substringToIndex:7] intValue];
    int left = 0;
    int right = self.phoneRecordCount;

    while (left <= right) {
        int middle = (left + right) / 2;
        int currentOffset = self.firstPhoneRecordOffset + middle * self.phoneFmtLength;
        if (currentOffset >= self.buf.length) {
            return nil;
        }

        int curPhone, recordOffset;
        char phoneType;
        [self.buf getBytes:&curPhone range:NSMakeRange(currentOffset, 4)];
        [self.buf getBytes:&recordOffset range:NSMakeRange(currentOffset + 4, 4)];
        [self.buf getBytes:&phoneType range:NSMakeRange(currentOffset + 8, 1)];

        if (curPhone > intPhone) {
            right = middle - 1;
        } else if (curPhone < intPhone) {
            left = middle + 1;
        } else {
            NSString *recordContent = [self getRecordContentFromOffset:recordOffset];
            return [PhoneNumber _formatPhoneContentWithPhoneNum:phoneNum recordContent:recordContent phoneType:phoneType];
        }
    }

    return nil;
}

- (NSString *)getRecordContentFromOffset:(int)startOffset {
    const char *bufPtr = self.buf.bytes + startOffset;
    int endOffset = startOffset;
    while (endOffset < self.buf.length && bufPtr[endOffset - startOffset] != '\0') {
        endOffset++;
    }
    NSData *recordData = [self.buf subdataWithRange:NSMakeRange(startOffset, endOffset - startOffset)];
    return [[NSString alloc] initWithData:recordData encoding:NSUTF8StringEncoding];
}

- (NSDictionary *)find:(NSString *)phoneNum {
    return [self _lookupPhone:phoneNum];
}

+ (NSString *)humanPhoneInfo:(NSDictionary *)phoneInfo {
    if (!phoneInfo) {
        return @"";
    }
    return [NSString stringWithFormat:@"%@|%@|%@|%@|%@|%@", phoneInfo[@"phone"], phoneInfo[@"province"], phoneInfo[@"city"], phoneInfo[@"zip_code"], phoneInfo[@"area_code"], phoneInfo[@"phone_type"]];
}

- (void)test {
    [self getPhoneDatMsg];
    NSLog(@"%@", [PhoneNumber humanPhoneInfo:[self find:@"15002103667"]]);
}


@end
